package com.kymatrix.mpo.plus.bpm.server.controller.definition;

import cn.hutool.core.collection.CollUtil;
import com.kymatrix.mpo.plus.bpm.server.convert.definition.BpmProcessDefinitionConvert;
import com.kymatrix.mpo.plus.bpm.server.flowable.candidate.strategy.BpmTaskCandidateStartUserSelectStrategy;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmCategoryEntity;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmFormEntity;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmProcessDefinitionInfoEntity;
import com.kymatrix.mpo.plus.bpm.server.model.form.process.PageQueryBpmProcessDefinitionReq;
import com.kymatrix.mpo.plus.bpm.server.model.form.process.QueryBpmProcessDefinitionResp;
import com.kymatrix.mpo.plus.bpm.server.service.BpmCategoryService;
import com.kymatrix.mpo.plus.bpm.server.service.BpmFormService;
import com.kymatrix.mpo.plus.bpm.server.service.BpmProcessDefinitionService;
import com.kymatrix.mpo.plus.common.business.common.PageResp;
import com.kymatrix.mpo.plus.common.business.common.ResultResp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import static com.kymatrix.mpo.plus.common.util.CollectionUtils.convertSet;


@Api(tags = "BPM 流程定义相关请求处理类")
@RestController
@Validated
public class BpmProcessDefinitionController {

    @Resource
    private BpmProcessDefinitionService processDefinitionService;
    @Resource
    private BpmFormService formService;
    @Resource
    private BpmCategoryService categoryService;

    @GetMapping("/bpm/process-definition/page")
    @ApiOperation(value = "获得流程定义分页")
    public ResultResp<PageResp<QueryBpmProcessDefinitionResp>> getProcessDefinitionPage(
            PageQueryBpmProcessDefinitionReq req) {
        PageResp<ProcessDefinition> pageResult = processDefinitionService.getProcessDefinitionPage(req);
        if (CollUtil.isEmpty(pageResult.getList())) {
            return ResultResp.ok(new PageResp<>());
        }

        // 获得 Category Map
        Map<String, BpmCategoryEntity> categoryMap = categoryService.getCategoryMap(
                convertSet(pageResult.getList(), ProcessDefinition::getCategory));
        // 获得 Deployment Map
        Map<String, Deployment> deploymentMap = processDefinitionService.getDeploymentMap(
                convertSet(pageResult.getList(), ProcessDefinition::getDeploymentId));
        // 获得 BpmProcessDefinitionInfoDO Map
        Map<String, BpmProcessDefinitionInfoEntity> processDefinitionMap = processDefinitionService.getProcessDefinitionInfoMap(
                convertSet(pageResult.getList(), ProcessDefinition::getId));
        // 获得 Form Map
        Map<String, BpmFormEntity> formMap = formService.getFormMap(
               convertSet(processDefinitionMap.values(), BpmProcessDefinitionInfoEntity::getFormId));
        return ResultResp.ok(BpmProcessDefinitionConvert.buildProcessDefinitionPage(
                pageResult, deploymentMap, processDefinitionMap, formMap, categoryMap));
    }

    @GetMapping ("/bpm/process-definition/list")
    @ApiOperation(value = "获得流程定义列表")
    public ResultResp<List<QueryBpmProcessDefinitionResp>> getProcessDefinitionList(
            @ApiParam(value = "SuspensionStateEnum.ACTIVE.getCode = 1")
            @RequestParam(value = "suspensionState") String suspensionState) {
        List<ProcessDefinition> list = processDefinitionService.getProcessDefinitionListBySuspensionState(suspensionState);
        if (CollUtil.isEmpty(list)) {
            return ResultResp.ok(Collections.emptyList());
        }
        // 获得 BpmProcessDefinitionInfoDO Map
        Set<String> ids = convertSet(list, ProcessDefinition::getId);
        
        Map<String, BpmProcessDefinitionInfoEntity> processDefinitionMap = processDefinitionService.getProcessDefinitionInfoMap(ids);
        return ResultResp.ok(BpmProcessDefinitionConvert.buildProcessDefinitionList(
                list, null, processDefinitionMap, null, null));
    }

    @GetMapping ("/bpm/process-definition/get")
    @ApiOperation(value = "获得流程定义")
    public ResultResp<QueryBpmProcessDefinitionResp> getProcessDefinition(
            @RequestParam(value = "id", required = false) String id,
            @RequestParam(value = "key", required = false) String key) {
        ProcessDefinition processDefinition = id != null ? processDefinitionService.getProcessDefinition(id)
                : processDefinitionService.getActiveProcessDefinition(key);
        if (processDefinition == null) {
            return ResultResp.ok(null);
        }
        BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(processDefinition.getId());
        List<UserTask> userTaskList = BpmTaskCandidateStartUserSelectStrategy.getStartUserSelectUserTaskList(bpmnModel);
        return ResultResp.ok(BpmProcessDefinitionConvert.buildProcessDefinition(
                processDefinition, null, null, null, null, bpmnModel, userTaskList));
    }

}
